﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Cyss.Core
{
    /// <summary>
    /// 
    /// </summary>
    public static class HttpClientExtensions
    {
        /// <summary>
        /// 获取文件
        /// </summary>
        /// <param name="client"></param>
        /// <param name="Url"></param>
        /// <returns></returns>
        public async static Task<BaseFileModel> GetFile(this HttpClient client, string Url)
        {
            var httpResponseMessage = await client.GetAsync(Url);
            var stream = await httpResponseMessage.Content.ReadAsStreamAsync();
            BaseFileModel baseFile = new BaseFileModel();
            baseFile.SetStream(stream);
            return baseFile;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="client"></param>
        /// <param name="requestUri"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public async static Task<T> PostReceiveObject<T>(this HttpClient client, string? requestUri, object model)
        {

            var content = new StringContent(JsonHelper.SerializeObject(model), Encoding.UTF8, MimeTypes.ApplicationJson);
            var response = await client.PostAsync(requestUri, content);
            if (response.IsSuccessStatusCode)
            {
                var responseString = await response.Content.ReadAsStringAsync();
                return JsonHelper.DeserializeObject<T>(responseString);
            }
            return default(T);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="client"></param>
        /// <param name="requestUri"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public async static Task<OperateResult> PostReceiveApiRespone(this HttpClient client, string? requestUri, object model)
        {
            try
            {
                var content = new StringContent(JsonHelper.SerializeObject(model), Encoding.UTF8, MimeTypes.ApplicationJson);
                var response = await client.PostAsync(requestUri, content);
                if (response.IsSuccessStatusCode)
                {
                    var responseString = await response.Content.ReadAsStringAsync();
                    return JsonHelper.DeserializeObject<OperateResult>(responseString);
                }
                else
                {
                    OperateResult OperateResult = new OperateResult();
                    OperateResult.IsSuccess = false;
                    OperateResult.Message = $"Url:{client.BaseAddress + requestUri} StatusCode:{response.StatusCode}  ReasonPhrase:{response.ReasonPhrase}";
                    return OperateResult;
                }
            }
            catch (Exception ex)
            {
                OperateResult OperateResult = new OperateResult();
                OperateResult.IsSuccess = false;
                OperateResult.Message = $"Url:{client.BaseAddress + requestUri} ExceptionMessage:{ex.Message}";
                return OperateResult;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="client"></param>
        /// <param name="requestUri"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public async static Task<OperateResult<T>> PostReceiveResponeObject<T>(this HttpClient client, string? requestUri, object model)
        {
            try
            {
                var content = new StringContent(JsonHelper.SerializeObject(model), Encoding.UTF8, MimeTypes.ApplicationJson);
                var response = await client.PostAsync(requestUri, content);
                if (response.IsSuccessStatusCode)
                {
                    var responseString = await response.Content.ReadAsStringAsync();
                    return JsonHelper.DeserializeObject<OperateResult<T>>(responseString);
                }
                else
                {
                    OperateResult<T> operateResult = new OperateResult<T>();
                    operateResult.IsSuccess = false;
                    operateResult.Message = $"Url:{client.BaseAddress + requestUri} StatusCode:{response.StatusCode}  ReasonPhrase:{response.ReasonPhrase}";
                    return operateResult;
                }
            }
            catch (Exception ex)
            {
                OperateResult<T> operateResult = new OperateResult<T>();
                operateResult.IsSuccess = false;
                operateResult.Message = $"Url:{client.BaseAddress + requestUri} ExceptionMessage:{ex.Message}";
                return operateResult;
            }


        }

        /// <summary>
        /// Post
        /// </summary>
        /// <param name="requestUri"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public async static Task<string> SendMessageAsync(this HttpClient httpClient, HttpRequestMessage message, string LogFileName = "")
        {
            HttpClientMessageModel logModel = new HttpClientMessageModel();
            logModel.ExecuteStartTime = DateTimeOffset.Now;
            try
            {
                logModel.Url =httpClient.FullUrl(message);
                logModel.Content = message.Content != null ? (await message.Content?.ReadAsStringAsync()) : string.Empty;
                logModel.HttpMethod = message.Method.Method;
                logModel.ContentType = string.Empty;
                logModel.Headers = string.Join(",", message.Headers.ToDictionary(x => x.Key, v => string.Join(";", v.Value.ToList())));
                var httpResponseMessage = await httpClient.SendAsync(message);
                logModel.IsSuccessStatusCode = httpResponseMessage.IsSuccessStatusCode;
                logModel.StatusMessage = httpResponseMessage.StatusCode + "/" + httpResponseMessage.ReasonPhrase;
                string responseString = await httpResponseMessage.Content.ReadAsStringAsync();
                logModel.ResponseString = responseString;
                if (httpResponseMessage.IsSuccessStatusCode == false)
                {
                    throw new Exception($"{httpResponseMessage.ReasonPhrase} {responseString}");
                }
                return responseString;
            }
            catch (Exception ex)
            {
                throw new Exception($"Request Error :url({logModel.Url}) ResponseMessage:" + ex.Message);
            }
            finally
            {
                logModel.ExecuteEndTime = DateTimeOffset.Now;
                LogSevice.Write(logModel.GetLogText(), LogFileName);
            }
        }
        private static string FullUrl(this HttpClient httpClient, HttpRequestMessage message)
        {
            if (message.RequestUri.OriginalString.IndexOf("http") >= 0)
            {
                return message.RequestUri.OriginalString;
            }
            if (httpClient!=null && httpClient.BaseAddress!=null)
            {
                return httpClient.BaseAddress.AbsoluteUri + message.RequestUri.OriginalString;
            }
            return message.RequestUri.OriginalString;
        }
        /// <summary>
        /// 获取文件
        /// </summary>
        /// <param name="httpClient"></param>
        /// <param name="message"></param>
        /// <param name="LogFileName"></param>
        /// <returns></returns>
        public async static Task<BaseFileModel> GetFileAsync(this HttpClient httpClient, HttpRequestMessage message, string LogFileName = "")
        {
            HttpClientMessageModel logModel = new HttpClientMessageModel();
            logModel.ExecuteStartTime = DateTimeOffset.Now;
            try
            {
                logModel.Url = message.RequestUri.OriginalString;
                logModel.Content = message.Content != null ? (await message.Content?.ReadAsStringAsync()) : string.Empty;
                logModel.HttpMethod = message.Method.Method;
                logModel.ContentType = string.Empty;
                logModel.Headers = string.Join(",", message.Headers.ToDictionary(x => x.Key, v => string.Join(";", v.Value.ToList())));
                var httpResponseMessage = await httpClient.SendAsync(message);
                logModel.IsSuccessStatusCode = httpResponseMessage.IsSuccessStatusCode;
                logModel.StatusMessage = httpResponseMessage.StatusCode + "/" + httpResponseMessage.ReasonPhrase;
                var responseBytes = await httpResponseMessage.Content.ReadAsByteArrayAsync();
                logModel.ResponseString = Convert.ToBase64String(responseBytes);
                if (httpResponseMessage.IsSuccessStatusCode == false)
                {
                    throw new Exception($"{httpResponseMessage.ReasonPhrase}");
                }
                BaseFileModel baseFile = new BaseFileModel();
                baseFile.FileBytes = responseBytes;
                return baseFile;
            }
            catch (Exception ex)
            {
                throw new Exception($"Request Error :url({logModel.Url}) ResponseMessage:" + ex.Message);
            }
            finally
            {
                logModel.ExecuteEndTime = DateTimeOffset.Now;
                LogSevice.Write(logModel.GetLogText(), LogFileName);
            }
        }

    }
}
